package com.fingard.dsp.bank.directbank.lzccb01;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.db.JDBCHelper;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.IBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.detail.RetAtsBatPayRecDetail;
import com.fingard.io.FileHelper;
import com.fingard.text.MFSHelper;
import com.fingard.text.StringHelper;
import com.fingard.util.SmbFileUtil;
import com.fingard.xml.XElement;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

import java.io.File;
import java.sql.Connection;
import java.util.*;

import static com.fingard.text.StringHelper.trimEndFileSp;

public class LZCCB01BatPayRec extends LZCCB01Base implements IBatPayRec {
    private static final String INSERTRECEIPT = "INSERT INTO REQSEQIDMAPPING(URID,BANKCODE,TRANSDATE,REQSEQID,BANKREQSEQID) values (?,?,?,?,?);";
    private static final String SELECTRECEIPT = "SELECT BANKREQSEQID,TRANSDATE FROM REQSEQIDMAPPING WHERE REQSEQID=? and BANKCODE=?;";


    //批量代付
    @Override
    public RetAtsBatPayRec d_1988_BatPay(ReqBatPayRec p_req1988) throws Exception {
        RetAtsBatPayRec retAts = new RetAtsBatPayRec(p_req1988.reqHeader);
        XmlTextWriter xmlWriter = new XmlTextWriter();//发送给银行的报文
        Connection conn = FGBiz.getLocalDbConn();

        String p_FileName = p_req1988.reqBatchNO + ".query";
        String tmpFilePath = getTempFileDirectory() + File.separator + "uploads";
        String p_FileFullPath = tmpFilePath + File.separator + p_FileName;
        try {
            Map<String, Object> resultAndfileContext = new HashMap<String, Object>();
            resultAndfileContext = writerPayFileContext(p_req1988);//文件内容拼接
            if ("false".equals(resultAndfileContext.get("result"))) {
                retAts.respCode = "-1";
                retAts.respInfo = "总笔数与循环数不一致";
                retAts.reqSeqID = p_req1988.reqBatchNO;
                retAts.writeRetToATS();
                return retAts;
            }
            WriteBankLogLn("批量代付生成文件本地路径:" + p_FileFullPath);
            FileHelper.writeFile(p_FileFullPath, resultAndfileContext.get("fileContext").toString(), getCharset());//将文件内容写入到DSP磁盘中
            WriteBankLogLn(p_req1988.reqBatchNO + "批号代付文件处理完毕,一共" + p_req1988.getTotalNum() + "条明细.");
        } catch (Exception e) {
            WriteBankLogLn("生成批付文件失败，返回异常信息：" + e.getMessage());
            retAts.respCode = "-1";
            retAts.respInfo = "生成批付文件失败，返回异常信息：" + e.getMessage();
            retAts.transState = PaymentState.FAIL_Batch;
            retAts.payInfoCode = PaymentState.FAIL_Batch;
            retAts.writeRetToATS();
            return retAts;
        }
        try {
            WriteBankLogLn("开始上传文件至共享文件夹...");
            WriteBankLogLn("前置机共享文件夹目录：" + trimEndFileSp(bankFront.bkTransFolder));
            //上传文件到前置机目录
            if (FileHelper.existFile(p_FileFullPath)) {
                String remotePath = trimEndFileSp(bankFront.bkTransFolder) + "/";
                int result = SmbFileUtil.smbUploading(p_FileFullPath, "", remotePath);
                if (result == -1) {
                    retAts.respCode = "-1";
                    retAts.respInfo = "上传文件到前置机目录异常";
                    retAts.writeRetToATS();
                    return retAts;
                } else if (result == 1) {
                    retAts.respCode = "-1";
                    retAts.respInfo = "文件已存在共享目录无需重复上传";
                    retAts.writeRetToATS();
                }
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = "批付文件不存在";
                retAts.writeRetToATS();
                return retAts;
            }

            //赋值通用参数
            LZCCB01Header bankHeader = new LZCCB01Header();
            bankHeader.trCode = "300006";
            bankHeader.reqNo = p_req1988.reqHeader.reqSeqID;
            bankHeader.fileFlag = "1";//文件标识 0-报文 1-文件
            writeCommonHeader(xmlWriter, bankHeader);

            xmlWriter.writeStartElement("body");
            xmlWriter.writeElementString("batch_no", p_req1988.reqBatchNO);
            xmlWriter.writeElementString("pay_acno", p_req1988.ownAct);//付款账号
            xmlWriter.writeElementString("pay_cur_code", convertCurToBank(p_req1988.ownCur));//币种-人民币
            xmlWriter.writeElementString("pay_acname", p_req1988.ownActName, true);
            xmlWriter.writeElementString("amt", p_req1988.totalAmt);//总金额
            xmlWriter.writeElementString("count", p_req1988.totalNum);//总笔数
            xmlWriter.writeElementString("purpose", p_req1988.useType, true);//用途
            xmlWriter.writeElementString("postscript", "", true);//附言
            xmlWriter.writeElementString("file_name", p_FileName);//提交的文件名
            xmlWriter.writeEndElement();//</body>
            xmlWriter.writeEndDocument();

            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());// 发送银行
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                // 解析银行返回
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String tmpRespCode = tmpBkReader.getFirstText("/ap/head/ret_code");
                    String tmpRetInfo = tmpBkReader.getFirstText("/ap/head/ret_info");
                    String tmpRetRxtInfo = tmpBkReader.getFirstText("/ap/head/ext_info");
                    String tmpsuccFlag = tmpBkReader.getFirstText("/ap/head/succ_flag");
                    if (tmpRespCode != null && "0000".equals(tmpRespCode) && "0".equals(tmpsuccFlag)) {
                        //该交易采用异步处理，银行先接受交易，返回企业交易受理成功，转账结果，由企业来查询交易处理结果。
                        //存入银行返回的入账日期，用于查询
                        String transDate = tmpBkReader.getFirstText("/ap/head/tr_acdt");
                        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
                        JDBCHelper.update(conn, INSERTRECEIPT, new Object[]{uuid, p_req1988.reqHeader.bankCode, transDate, p_req1988.reqBatchNO, p_req1988.reqBatchNO});
                        retAts.respCode = "0";
                        retAts.respInfo = "交易结果未知，待查询";
                        retAts.reqSeqID = p_req1988.reqHeader.reqSeqID;
                        retAts.transState = tmpRespCode + "+batpay";
                        retAts.payInfoCode = tmpRespCode + "+batpay";
                    } else {
                        retAts.respCode = "0";
                        retAts.reqSeqID = p_req1988.reqHeader.reqSeqID;
                        retAts.transState = tmpRespCode + "+" + tmpsuccFlag;
                        retAts.payInfoCode = tmpRespCode + "+" + tmpsuccFlag;
                        retAts.respInfo = StringHelper.joinNotEmpty("+", tmpRetInfo, tmpRetRxtInfo);
                    }
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = tmpSbMsg.toString();
                }
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = tmpStrRet[1];
            }

        } catch (Exception e) {
            retAts.respCode = "-1";
            retAts.respInfo = e.toString();
            WriteBankLogLn(e);
        } finally {
            conn.close();
        }
        retAts.writeRetToATS();
        return retAts;
    }


    //批量代付状态查询
    @Override
    public RetAtsQryBatPayRec d_1998_QryBatPay(ReqQryBatPayRec p_req1998) throws Exception {
        /**
         * 逻辑：
         * 在去前置机拿取批量代付存入的单笔明细文件，文件名为批量支付流水号（但是单笔明细文件，里面没有单笔的支付状态）
         * 【银行回复 批量代付存入的明细文件 字段[凭证码]即为支付流水号，通过这个再去单笔查询支付状态】
         */
        RetAtsQryBatPayRec retAts = new RetAtsQryBatPayRec(p_req1998.reqHeader);
        Connection conn = FGBiz.getLocalDbConn();
        try {
            /**
             * 根据批量支付流水号去前置机获取批量支付时候存入的批量单笔明细文件
             * 再根据单笔明细的支付流水号，去查单笔的支付状态和明细
             */
            //去前置机获取批量支付存入的文件
            String tmpBatchFileName = p_req1998.reqHeader.reqSeqID + ".query";//批量支付文件名
            String tmpResultData = null;//读取的数据
            //下载共享目录批量查询文件
            String downloadFilePath = trimEndFileSp(bankFront.bkTransFolder) + File.separator;//共享目录路径
            String p_FileFullPath = getTempFileDirectory() + File.separator + Format.Time6Format.format(new Date());//下载到的本地路径
            StringBuilder p_sb = new StringBuilder();
            if (SmbFileUtil.smbDownload(p_FileFullPath, downloadFilePath, tmpBatchFileName, p_sb) == 1) {
                WriteBankLogLn("文件下载成功，位于：" + p_FileFullPath);
                p_FileFullPath = p_FileFullPath + File.separator + tmpBatchFileName;
                tmpResultData = FileHelper.readFileText(p_FileFullPath, getCharset());
            } else {
                retAts.writeRespCode("-1");
                retAts.writeRespInfo(p_sb.toString());
                retAts.writeEnd();
                return retAts;
            }

            if (tmpResultData == null) {
                this.WriteBankLogLn("读取前置数据文件返回为null，需确认前置文件夹配置和文件是否存在");
            } else {
                this.WriteBankLogStep3(tmpResultData);
            }

            WriteBankLogLn("银行查询文件返回内容为：" + tmpResultData);
            StringBuilder tmpSbLog = new StringBuilder();
            String tmpLocalMarkPath = getTempFileDirectory() + File.separator + "uploads" + File.separator + tmpBatchFileName;
            WriteBankLogLn2("批次流水映射文件路径: " + tmpLocalMarkPath);
            File localMarkFile = new File(tmpLocalMarkPath);
            if (!localMarkFile.exists()) {
                retAts.respCode = "-1";
                retAts.respInfo = "批次流水映射文件未生成,未发生交易!";
                retAts.writeAfterDetail();
                return retAts;
            }
            String tmpSeqIDData = FileHelper.readToString(localMarkFile, getCharset());
            WriteBankLogLn2("本地流水映射文件内容:" + tmpSeqIDData);
            if (StringHelper.isNullOrEmpty(tmpSeqIDData)) {
                retAts.respCode = "-1";
                retAts.respInfo = "批次流水映射文件内容为空,未发生交易!";
                retAts.writeAfterDetail();
                return retAts;
            }
            //处理数据内容
            ArrayList<String[]> tmpArrayList = MFSHelper.getTextArray(tmpResultData, "|", 22, -1, tmpSbLog);
            if (Integer.parseInt(p_req1998.totalNum) != tmpArrayList.size() - 1) {
                retAts.respCode = "-1";
                retAts.respInfo = "该请求查询批次的总笔数与获取文件数据交易笔数不相等！";
                retAts.writeAfterDetail();
                return retAts;
            }

            if (tmpSbLog.length() == 0) {
                retAts.reqSeqID = p_req1998.reqHeader.reqSeqID;
                retAts.respCode = "0";
                retAts.respInfo = "查询批量支付状态操作成功！";
                for (int i = 1; i < tmpArrayList.size(); i++) {
                    String[] tmpEachArr = tmpArrayList.get(i);
                    /**
                     * 0凭证类型|1凭证号(流水号)|2收款账号|3收款币种|4收款户名|5收款地址|6金额|7账簿标志|8付款账簿号|9付款账簿名|10收款行号|
                     * 11收款行名|12跨行标志|13同城异地|14加急标志|15用途|16附言|17预约标志|18预约日期|19预约时间|20收款方手机号码|
                     * 21是否保存收款方信息|
                     */
                    RetAtsBatPayRecDetail tmpRetDetail = new RetAtsBatPayRecDetail();
                    tmpRetDetail.payAct = p_req1998.ownAct;//付方账号
                    tmpRetDetail.recAct = tmpEachArr[2];//收方账号
                    tmpRetDetail.curType = convertCurToATS(tmpEachArr[3]);//币种
                    tmpRetDetail.payAmount = tmpEachArr[6];//交易金额
                    tmpRetDetail.memo = tmpEachArr[16];//备注
                    tmpRetDetail.usage = tmpEachArr[15];//用途
                    tmpRetDetail.postScript = tmpEachArr[1];//批次内每一笔的流水号

                    /**
                     * 根据1凭证号(流水号)去查询单笔的交易状态
                     */
                    XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
                    //赋值通用参数
                    LZCCB01Header bankHeader = new LZCCB01Header();
                    bankHeader.trCode = "200205";
                    bankHeader.reqNo = tmpEachArr[1];
                    bankHeader.fileFlag = "0";//文件标识 0-报文 1-文件
                    //写入LZCCB01通用的头部节点
                    writeCommonHeader(xmlWriter, bankHeader);
                    XElement tmpXElement = new XElement("body", "");
                    tmpXElement.addChild(new XElement("cert_no", tmpEachArr[1]));//企业erp[账务]流水号
                    tmpXElement.addChild(new XElement("req_no", ""));//企业erp［请求］流水号
                    Map<String, Object> map = JDBCHelper.execQuerySingle(conn, SELECTRECEIPT, new Object[]{p_req1998.reqBatchNO, p_req1998.reqHeader.bankCode});
                    tmpXElement.addChild(new XElement("tr_acdt", map.get("TRANSDATE").toString()));
                    tmpXElement.addChild(new XElement("cms_corp_no", bankFront.corpNo));//客户号
                    xmlWriter.writeXElement(tmpXElement);
                    xmlWriter.writeEndElement();
                    xmlWriter.writeEndDocument();

                    String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());

                    if (tmpStrRet[0].length() == 0) {
                        StringBuilder tmpSbMsg = new StringBuilder();
                        XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                        if (tmpBkReader != null) {
                            String tmpRespCode = tmpBkReader.getFirstText("/ap/head/ret_code");
                            String tmpRetInfo = tmpBkReader.getFirstText("/ap/head/ret_info");
                            String tmpRetRxtInfo = tmpBkReader.getFirstText("/ap/body/error_info");
                            String tmpsuccFlag = tmpBkReader.getFirstText("/ap/head/succ_flag");
                            if (tmpRespCode != null && "0000".equals(tmpRespCode)) {
                                String stat = tmpBkReader.getFirstText("/ap/body/stat");
                                tmpRetDetail.result = tmpRespCode + "+" + stat;
                                tmpRetDetail.payInfoCode = tmpRespCode + "+" + stat;
                            } else {
                                tmpRetDetail.result = tmpRespCode + "+" + tmpsuccFlag;
                                tmpRetDetail.payInfoCode = tmpRespCode + "+" + tmpsuccFlag;
                            }
                        } else {
                            tmpRetDetail.result = "receiveFailure";
                            tmpRetDetail.payInfoCode = "receiveFailure";
                        }
                    } else {
                        tmpRetDetail.result = "receiveFailure";
                        tmpRetDetail.payInfoCode = "receiveFailure";
                    }
                    retAts.writeRetDetail(tmpRetDetail);
                }
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = tmpSbLog.toString();
                retAts.writeAfterDetail();
                return retAts;
            }
        } catch (Exception e) {
            retAts.respCode = "-1";
            retAts.respInfo = e.getMessage();
            e.printStackTrace();
            retAts.writeAfterDetail();
            return retAts;
        }

        retAts.writeAfterDetail();
        return retAts;
    }

    @Override
    public RetAtsBatPayRec d_9188_BatPay(ReqBatPayRec p_req9188) throws Exception {
        return null;
    }

    @Override
    public RetAtsQryBatPayRec d_9198_QryBatPay(ReqQryBatPayRec p_req9198) throws Exception {
        return null;
    }
}
